#include "SocketKernel.h"
#include "ListenSocket.h"
#include "ServerSocket.h"
#include "MessagePort.h"

namespace cupid
{

ISocketKernel* ISocketKernel::createNew()
{
	return new SocketKernel;
}

//////////////////////////////////////////////////////////////////////
// interface
//////////////////////////////////////////////////////////////////////
bool SocketKernel::create(IMessagePort* port)
{
	m_msgPort = port;
	m_msgPort->open();
	m_listen = ListenSocket::createNew();

	if(!m_listen->listen(SERVER_LISTEN_PORT))
		return false;

	return true;		
}

//////////////////////////////////////////////////////////////////////
bool SocketKernel::processMsg(int idPacket, void* buf, int type, int  from)
{
	switch(idPacket)
	{
	case	SOCKET_SENDCLIENTMSG:
		{
			const SENDCLIENTMSG_PACKET0* pack = (SENDCLIENTMSG_PACKET0*)buf;
			if(pack->idSocket >= m_setSocket.size())
				break;

			if(m_setSocket[pack->idSocket])
			{
				char buffer[MAX_PACKETSIZE];
				int	packetSize = unitePacket(buffer, MAX_PACKETSIZE, pack->idPacket, pack->buf, pack->size);
				ASSERT(packetSize);
				if(packetSize)
				{
					clock_t	clkDebug = clock();		// debug
					m_setSocket[pack->idSocket]->sendPacket(buffer, packetSize);
				}
			}
		}
		break;
	}

	return true;
}

//////////////////////////////////////////////////////////////////////
bool SocketKernel::processSocket()
{
	fd_set	readmask;
	FD_ZERO(&readmask);
	FD_SET(m_listen->socket(), &readmask);
	for(int i = 0; i < m_setSocket.size(); i++)
	{
		if(!m_setSocket[i])
			continue;

		FD_SET(m_setSocket[i]->socket(), &readmask);
	}

	int	nBlockMilli = 0;
	struct timeval	timeout;
	timeout.tv_sec	= (nBlockMilli*1000) / 1000000;
	timeout.tv_usec = (nBlockMilli*1000) % 1000000;
	int ret = select(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) 0, &timeout);

	if(FD_ISSET(m_listen->socket(), &readmask))
	{
		acceptNewSocket();
	}

	for( int i = m_setSocket.size()-1; i >= 0; i--)
	{
		if(!m_setSocket[i])
			continue;

		int		bufLen = 0;
		const char* buf = m_setSocket[i]->getPacket(&bufLen);
		if(buf && bufLen > 0)
		{
			int		idPacket;
			char*	msg;
			int		msgSize;
			int		packetSize;
			if(( packetSize = splitPacket(buf, bufLen, &idPacket, &msg, &msgSize) ))
			{
				char	bufPacket[MAX_MESSAGESIZE];
				CLIENTMSG_PACKET0* packet = (CLIENTMSG_PACKET0*)bufPacket;
				packet->idSocket	= i;
				packet->idPacket	= idPacket;
				packet->size		= msgSize;
				memcpy(packet->buf, msg, msgSize);
				m_msgPort->send(m_setProcessID[i], KERNEL_CLIENTMSG, STRUCT_TYPE(bufPacket), bufPacket);

				m_setSocket[i]->clearPacket(packetSize);

			}
		} 
	} 
	return true;	
}

//////////////////////////////////////////////////////////////////////
bool SocketKernel::onTimer(time_t tCurr)
{

	return true;	
}

//////////////////////////////////////////////////////////////////////
bool SocketKernel::release()
{
	m_listen->close();
	for(int i = m_setSocket.size()-1; i >= 0; i--)
	{
		if(m_setSocket[i])
		{
			m_setSocket[i]->close();
			delete m_setSocket[i];
		}
	}
	//m_msgPort->close();
	delete this;
	return true;		
}

//////////////////////////////////////////////////////////////////////
// inside
//////////////////////////////////////////////////////////////////////
void SocketKernel::acceptNewSocket()
{
	SOCKET socket = m_listen->accept();
	if(socket != INVALID_SOCKET)
	{
		IServerSocket* sock = IServerSocket::createNew(socket);
		if(sock)
		{
			BOOL	bInsertOk = false;
			for(int i = 0; i < m_setSocket.size(); i++)
			{
				if(!m_setSocket[i])
				{
					m_setSocket[i]			= sock;
					m_setProcessID[i]		= MSGPORT_WORLD;
					break;
				}
			}
			if(!bInsertOk)
			{
				m_setSocket.push_back(sock->getInterface());
				m_setProcessID.push_back(MSGPORT_WORLD);
			}
		}
	}
}

}